package com.example.demo.util;

import java.io.*;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.bouncycastle.util.encoders.Base64;

/**
 * Java实现数据压缩
 * ZLib压缩工具
 */
public abstract  class ZLibUtils {
    /**
     * 压缩
     *
     * @param data
     *            待压缩数据
     * @return byte[] 压缩后的数据
     */
    public static byte[] compress(byte[] data) {
        byte[] output = new byte[0];
        Deflater compresser = new Deflater();

        compresser.reset();
        compresser.setInput(data);
        compresser.setLevel(9);
        compresser.finish();

        ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
        try {
            byte[] buf = new byte[1024];
            while (!compresser.finished()) {
                int i = compresser.deflate(buf);
                bos.write(buf, 0, i);
            }
            output = bos.toByteArray();
        } catch (Exception e) {
            output = data;
            e.printStackTrace();
        } finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        compresser.end();
        return output;
    }

    /**
     * 压缩
     *
     * @param data
     *            待压缩数据
     *
     * @param os
     *            输出流
     */
    public static void compress(byte[] data, OutputStream os) {
        DeflaterOutputStream dos = new DeflaterOutputStream(os);

        try {
            dos.write(data, 0, data.length);

            dos.finish();

            dos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压缩
     *
     * @param data
     *            待压缩的数据
     * @return byte[] 解压缩后的数据
     */
    public static byte[] decompress(byte[] data) {
        byte[] output = new byte[0];

        Inflater decompresser = new Inflater();
        decompresser.reset();
        decompresser.setInput(data);

        ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
        try {
            byte[] buf = new byte[1024];
            while (!decompresser.finished()) {
                int i = decompresser.inflate(buf);
                o.write(buf, 0, i);
            }
            output = o.toByteArray();
        } catch (Exception e) {
            output = data;
            e.printStackTrace();
        } finally {
            try {
                o.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        decompresser.end();
        return output;
    }

    /**
     * 解压缩
     *
     * @param is
     *            输入流
     * @return byte[] 解压缩后的数据
     */
    public static byte[] decompress(InputStream is) {
        InflaterInputStream iis = new InflaterInputStream(is);
        ByteArrayOutputStream o = new ByteArrayOutputStream(1024);
        try {
            int i = 1024;
            byte[] buf = new byte[i];

            while ((i = iis.read(buf, 0, i)) > 0) {
                o.write(buf, 0, i);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return o.toByteArray();
    }



    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     */
    public static String readFileByLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;

        StringBuffer bf=new StringBuffer();
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
//            int line = 1;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
//                // 显示行号
//                System.out.println("line " + line + ": " + tempString);
//                line++;

                bf.append(tempString);
                bf.append(System.getProperty("line.separator"));
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return  bf.toString();
    }

    //字符串转16进制
    public static String strTo16(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            int much = 0;
            if(ch % 3 == 0){
                much = 222;
            }else if(ch % 3 ==1){
                much = 242;
            }else{
                much = 181;
            }
            String s4 = Integer.toHexString(much-ch);
            str = str + s4;
        }
        return str;
    }

    //16进制转字符串
    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        int ch =0 ;
        int ch_t=0 ;
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                ch = Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);

                if(ch % 3 == 0){
                    ch_t = 222-ch;
                }else if(ch % 3 ==1){
                    ch_t = 242-ch;
                }else{
                    ch_t = 181-ch;
                }
                baKeyword[i] = (byte) (0xff & ch_t);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    public static String huafei_enc(String s,String encode) throws UnsupportedEncodingException {
        byte[] data = ZLibUtils.compress(s.getBytes(encode));
        String rs = new String(Base64.encode(data),encode);

        return strTo16(rs).toLowerCase();
    }

    public static String huafei_dec(String s,String encode) throws UnsupportedEncodingException {
        byte[] output =Base64.decode( hexStringToString(s).getBytes(encode));
        output = ZLibUtils.decompress(output);
        return new String(output,encode);
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String encode = "utf-8";
        String str = "{'action':'login','data':{'uname':'test','upwd':'123123'}}";
        String e = huafei_enc(str,encode);
        System.out.println("定义加密:" + e);
        System.out.println("定义解密:" + huafei_dec("5090446c5f4aa568a67f47683bc1a3ab9d7f866b8a7d86689da58ea08aae4a7f625f62ab44725c7c3b9d7c688a8d879365a58566a569477f7c9da583bb8da69372a0919d823eafac7174ab5f91837f9c4a839d87858bb5b5",encode).trim());
    }
}